import json

import pytest
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.test import Client

from byxiaomi.models import FeedBack


@pytest.fixture
def client():
    return Client()


"""
因为我们有user_client,这个fixture中有一个用户,有用户肯定是存在数据库中的,有数据库了那肯定也是可以操作数据库的！！！
# 可以操作数据库的client
@pytest.fixture
def db_client(_django_db_helper, client):
    return client
"""


@pytest.fixture
def user():
    # 创建一个账号,使用了这个fixture则表明：数据库中有一个账号(username=xiaomi)
    new_user = User.objects.create(
        email="xiaomi@qq.com",
        username="xiaomi",
        password="123123",
    )
    return new_user


@pytest.fixture
def use_commented(user):
    # 方式1
    # data = {
    #     "quality": 5,
    #     "attitude": 5,
    #     "speed": 5,
    #     "text": "fixture中的数据,用户已经评论过了......",
    #     "annoy": True,
    #     "user_id": user.id
    # }
    # FeedBack.objects.create(**data)
    print(f"{user.id=},{user.username=}")
    # 方式2
    obj = FeedBack()
    obj.quality = 5
    obj.attitude = 4
    obj.speed = 3
    obj.text = "fixture中的数据,用户已经评论过了......"
    obj.annoy = 1
    obj.user = User.objects.get(username="xiaomi")

    obj.save()

    return user


@pytest.fixture
def login_client(client, user):
    # 使用user强制登录
    client.force_login(user)

    return client


def test_register_get(client):
    res: HttpResponse = client.get("/accounts/register")

    assert res.status_code == 200

    assert "邮箱地址" in res.text
    assert "用户名" in res.text
    assert "密码" in res.text
    assert "确认密码" in res.text


@pytest.mark.django_db
@pytest.mark.parametrize(
    "email,username,password,confirm_password,msg, status_code,code",
    [
        ("123@qq.com", "", "123123", "123123", "username 不能为空......", 422, -1),
        ("", "xiaomi", "123123", "123123", "email 不能为空......", 422, -1),
        ("123@qq.com", "xiaomi", "", "123123", "password 不能为空......", 422, -1),
        (
            "123@qq.com",
            "xiaomi",
            "123123",
            "",
            "confirm_password 不能为空......",
            422,
            -1,
        ),
        ("123@qq.com", "xiaomi", "123", "321", "两次输入的密码不一致......", 422, -2),
        ("123@qq.com", "xiaomi", "123", "123", "密码长度不能小于6位......", 422, -3),
        (
            "xiaomi@qq.com",
            "xiaomi",
            "123123",
            "123123",
            "xiaomi,该用户已存在......",
            400,
            -4,
        ),
        (
            "xiaomi24@qq.com",
            "xiaomi24",
            "123123",
            "123123",
            "xiaomi24注册成功!",
            200,
            0,
        ),
    ],
    ids=[
        "注册失败(用户名为空)",
        "注册失败(邮箱为空)",
        "注册失败(密码为空)",
        "注册失败(确认密码为空)",
        "注册失败(两次密码输入不一致)",
        "注册失败(密码长度小于6位)",
        "注册失败(用户已经注册)",
        "注册成功(输入信息正确)",
    ],
)
def test_register_post(
    client,
    user,
    email,
    username,
    password,
    confirm_password,
    msg,
    status_code,
    code,
):
    # 在注册之前查询数据库中有多少个用户
    assert len(list(User.objects.all())) == 1
    assert User.objects.all()[0].username == "xiaomi"

    res: HttpResponse = client.post(
        "/accounts/register",
        data={
            "email": email,
            "username": username,
            "password": password,
            "confirm_password": confirm_password,
        },
        content_type="application/json",
    )

    text = res.text
    data = json.loads(text)
    assert res.status_code == status_code
    assert data["msg"] == msg
    assert data["code"] == code
    # 在注册之后查询数据库中有多少个用户
    user_list = list(User.objects.all())
    len(user_list)

    if data["code"] == 0:
        assert len(list(User.objects.all())) == 2
        assert User.objects.all()[1].username == "xiaomi24"
    else:
        assert len(list(User.objects.all())) == 1


def test_submit_get_annoy(client):
    res = client.get("/example/submit")
    assert res.status_code == 302


@pytest.mark.django_db
def test_submit_get_logined(login_client):
    resp = login_client.get("/example/submit")
    assert resp.status_code == 200
    assert "商品质量" in resp.text
    assert "客服态度" in resp.text
    assert "物流速度" in resp.text
    assert "是否匿名" in resp.text
    assert "评论内容" in resp.text
    assert "请输入您的评论，谢谢！" in resp.text


# 评论内容为空时,返回HTML(重定向到http://127.0.0.1:8000/example/submit)
@pytest.mark.django_db
def test_submit_post_text_kong(login_client):
    resp = login_client.post(
        "/example/submit",
        data={"quality": 5, "attitude": 5, "speed": 5, "text": "", "annoy": True},
        content_type="application/json",
    )

    assert resp.status_code == 302


@pytest.mark.django_db
def test_submit_post_text(login_client):
    # 评论之前,获取评论列表数据(为空)
    obj_list = list(FeedBack.objects.all())
    obj_count = len(obj_list)
    assert obj_count == 0

    resp = login_client.post(
        "/example/submit",
        data={
            "quality": 5,
            "attitude": 5,
            "speed": 5,
            "text": "username=xiaomi,这是xiaomi的评论,商品质量很好！！！",
            "annoy": True,
        },
        content_type="application/json",
    )

    assert resp.status_code == 200
    res_data = json.loads(resp.content.decode())

    assert res_data["code"] == 0
    assert res_data["msg"] == "评论保存成功"
    assert res_data["data"] == {
        "quality": 5,
        "attitude": 5,
        "speed": 5,
        "text": "username=xiaomi,这是xiaomi的评论,商品质量很好！！！",
        "annoy": True,
    }
    # 数据库断言
    # 评论之后,获取评论列表数据(有1提条评论)
    obj_list = list(FeedBack.objects.all())
    obj_count = len(obj_list)
    assert obj_count == 1

    obj = obj_list[0]
    # assert obj.username == "xiaomi"
    assert obj.text == "username=xiaomi,这是xiaomi的评论,商品质量很好！！！"


@pytest.mark.django_db
def test_submit_post_text_repeat(login_client, use_commented):
    # 评论之前,获取评论列表数据(1条评论)
    obj_list = list(FeedBack.objects.all())
    obj_count = len(obj_list)
    assert obj_count == 1

    resp = login_client.post(
        "/example/submit",
        data={
            "quality": 5,
            "attitude": 5,
            "speed": 5,
            "text": "用户已经进行过评论了,再次进行评论",
            "annoy": True,
        },
        content_type="application/json",
    )

    assert resp.status_code == 400
    res_data = json.loads(resp.content.decode())

    assert res_data["code"] == -1
    assert res_data["msg"] == "该用户已经评论过了......"

    # 数据库断言
    # 评论之后,获取评论列表数据(还是只有有1提条评论)
    obj_list = list(FeedBack.objects.all())
    obj_count = len(obj_list)
    assert obj_count == 1


@pytest.mark.parametrize("method", ["get", "post", "put", "delete", "xiaomi"])
def test_result_all_method(method, client):
    resp: HttpResponse = client.generic(method=method, path="/example/result")

    assert resp.status_code == 200
    assert "评论成功！" in resp.text
